#include "XFunctionParser.h"
#include "XBasicParseNodes.h"
#include <cctype>
#include <stack>

using namespace std;

XFunctionParser::XFunctionParser()
{
}


XFunctionParser::~XFunctionParser()
{
}

void XFunctionParser::genTokenStrings()
{
    polandTokenStrings.clear();
    int cur = 0;
    while (cur < polandString.size()) {
        while (polandString[cur] == ' ') {
            cur++;
        }
        string str;
        while (polandString[cur] != ' ' && polandString[cur] != '\0') {
            str += polandString[cur];
            cur++;
        }
        polandTokenStrings.push_back(str);
    }
}

vector<string> XFunctionParser::getPolandTokenString() const
{
    return polandTokenStrings;
}

void XFunctionParser::genParseTree()
{
    delete root;
    stack<XAbstractParseNode *> stk;
    for (int i = 0; i < polandTokenStrings.size(); i++) {
        string str = polandTokenStrings[i];
        if (str == "x" || str == "y" || str == "z") {
            XVariableParseNode *node = new XVariableParseNode;
            node->index = str[0];
            stk.push(node);
            if (str[0] == 'x') {
                arrX.push_back(node);
            } else if (str[1] == 'y') {
                arrY.push_back(node);
            } else {
                arrZ.push_back(node);
            }
        } else if (isdigit(str[0])
            || str[0] == '.' 
            || str[0] == '-' && isdigit(str[1])) {
            double val = atof(str.c_str());
            XVariableParseNode *node = new XVariableParseNode;
            node->value = val;
            stk.push(node);
        } else if (str == "+") {
            XPlusParseNode *node = new XPlusParseNode;
            XAbstractParseNode *b = stk.top();
            stk.pop();
            XAbstractParseNode *a = stk.top();
            stk.pop();
            node->childs[0] = a;
            node->childs[1] = b;
            stk.push(node);
        } else if (str == "-") {
            XMinusParseNode *node = new XMinusParseNode;
            XAbstractParseNode *b = stk.top();
            stk.pop();
            XAbstractParseNode *a = stk.top();
            stk.pop();
            node->childs[0] = a;
            node->childs[1] = b;
            stk.push(node);
        }
    }
    root = stk.top();
}

double XFunctionParser::getFunction(double x, double y, double z)
{
    for (int i = 0; i < arrX.size(); i++) {
        arrX[i]->value = x;
    }
    for (int i = 0; i < arrY.size(); i++) {
        arrY[i]->value = y;
    }
    for (int i = 0; i < arrZ.size(); i++) {
        arrZ[i]->value = z;
    }
    root->updateValue();
    return root->getValue();
}

#include <iostream>

void XFunctionParser::dfs(XAbstractParseNode *r)
{
    if (r == nullptr) {
        return;
    }
    if (r->isLeaf()) {
        XVariableParseNode *rv = (XVariableParseNode *)(r);
        cout << rv->index;
    } else {
        XBranchParseNode *rb = (XBranchParseNode *)r;
        cout << "(";
        dfs(rb->childs[0]);
        cout << " " << rb->getName() << " ";
        dfs(rb->childs[1]);
        cout << ")";
    }
}
